<script setup>
import { MarkerType, VueFlow, useVueFlow } from '@vue-flow/core'
import { MiniMap } from '@vue-flow/minimap'
import { ref } from 'vue'
import DropzoneBackground from './background/DropzoneBackground.vue'
import Sidebar from './bar/Sidebar.vue'
import useDragAndDrop from './bar/useDnD'
import Controls from './controls/Controls.vue'
import EdgeControls from './controls/EdgeControls.vue'
import InteractionControls from './controls/InteractionControls.vue'
import CommonEdge from './edge/CommonEdge.vue'
import CommonLine from './edge/CommonLine.vue'
import BooleanNode from './node/BooleanNode.vue'
import CommonNode from './node/CommonNode.vue'
import ForNode from './node/ForNode.vue'
import GroupNode from './node/GroupNode.vue'
import IteratorNode from './node/IteratorNode.vue'
import SwitchNode from './node/SwitchNode.vue'

const { 
  onConnect, addEdges, updateEdge, onPaneReady, onPaneClick,
  onNodeDragStop, onNodeDrag, isNodeIntersecting, getIntersectingNodes, getNodes, getEdges, updateNode,
  setViewport, toObject,
  onEdgeClick, 
} = useVueFlow()

const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()

const nodes = ref([])
const edges = ref([])

onPaneReady(({ fitView }) => {
  setViewport({ x: 0, y: 0, zoom: 1 })
})

onConnect(connection => {
  connection.animated = true
  connection.id = guid()

  // connection.type = 'button'
  connection.type = 'custom'
  connection.label = ''
  connection.updatable = true
  connection.markerEnd = MarkerType.ArrowClosed
  // connection.class = 'normal-edge'
  addEdges(connection)
})


onNodeDrag(({ intersections }) => {
  // const intersectionIds = intersections.map((intersection) => intersection.id)
  // for (const node of getNodes.value) {
  //   const isIntersecting = intersectionIds.includes(node.id)
  //   updateNode(node.id, { class: isIntersecting ? 'intersecting' : '' })
  // }
})

onNodeDragStop(({ event, nodes, node, intersections }) => {
  const intersectionIds = intersections.map(intersection => intersection.id)
  for (const groupNode of getNodes.value) {
    const isIntersecting = intersectionIds.includes(groupNode.id)
    if(isIntersecting && groupNode.type === 'group'){
      // console.log('onNodeDragStop', { node, groupNode })

      if(!groupNode.parentNode){
        node.parentNode = groupNode.id
        node.expandParent = true
      }
    }
  }

})



function guid() {
  return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = Math.random() * 16 | 0,
      v = c == 'x' ? r : (r & 0x3 | 0x8)
    
    return v.toString(16)
  })
}

const interactionControlsShow = ref(false)

// 当前选中路径
const edgeControlsKey = ref(0)
const currEdge = ref({})
const edgeControlsShow = ref(false)
// 点击连线
onEdgeClick((event, edge) => {
  currEdge.value = event.edge
  edgeControlsOpen()
})

// 路径设置面板隐藏
const edgeControlsClose = () => {
  console.log("edgeControlsClose")
  edgeControlsShow.value = false
  currEdge.value.selected = false
  currEdge.value = {}
}

// 路径设置面板显示
const edgeControlsOpen = (edge) => {
  if(edge){
    currEdge.value = edge
  }
  edgeControlsKey.value = currEdge.value.id;
  edgeControlsShow.value = true
}

// 点击画板
onPaneClick((e)=>{
  edgeControlsClose()
})
</script>

<template>
  <div
    class="dndflow"
    @drop="onDrop"
  >
    <Sidebar />

    <VueFlow 
      :nodes="nodes" 
      :default-viewport="{ zoom: 1 }"
      :min-zoom="0.1"
      :max-zoom="3"
      :connection-radius="30"
      auto-connect
      class="custom-node-flow interactionflow"
      @dragover="onDragOver"
      @dragleave="onDragLeave"
    >
      <DropzoneBackground
        :style="{
          backgroundColor: isDragOver ? '#e7f3ff' : 'transparent',
          transition: 'background-color 0.2s ease',
        }"
      />

      <template #node-common="{ id, data }"> <CommonNode :id="id" :data="data" /> </template>
      <template #node-switch="{ id, data }"> <SwitchNode :id="id" :data="data" /> </template>
      <template #node-boolean="{ id, data }"> <BooleanNode :id="id" :data="data" /> </template>
      <template #node-for="{ id, data }"> <ForNode :id="id" :data="data" /> </template>
      <template #node-iterator="{ id, data }"> <IteratorNode :id="id" :data="data" /> </template>
      <template #node-group="{ id, data }"> <GroupNode :id="id" :data="data" /> </template>

      <template #edge-custom="props">
        <CommonEdge v-bind="props" @edgeControlsOpen="edgeControlsOpen" @edgeControlsClose="edgeControlsClose" />
      </template>

      <template #connection-line="{ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }">
        <CommonLine
          :source-x="sourceX"
          :source-y="sourceY"
          :target-x="targetX"
          :target-y="targetY"
          :source-position="sourcePosition"
          :target-position="targetPosition"
        />
      </template>

      <InteractionControls v-show="interactionControlsShow" />
      <EdgeControls v-if="edgeControlsShow" :key="edgeControlsKey" :edge="currEdge" @edgeControlsClose="edgeControlsClose"/>

      <Controls @update-interaction-controls="(val) => interactionControlsShow = val" />
      <MiniMap />
    </VueFlow>
  </div>
</template>

<style>
@import '@vue-flow/core/dist/style.css';
@import "@vue-flow/core/dist/theme-default.css";
@import "@vue-flow/controls/dist/style.css";
@import "@vue-flow/minimap/dist/style.css";
@import "@vue-flow/node-resizer/dist/style.css";


.layout-wrapper-ivy{
  block-size: 100%;
}

.vue-flow__minimap {
  transform: scale(75%);
  transform-origin: bottom right;
}

.dndflow{
  display:flex;
  flex-direction:column;
  block-size:100%
}

.dndflow aside{
  background:rgba(16,185,129,75%);
  border-inline-end:1px solid #eee;
  box-shadow:0 5px 10px 0 rgba(0,0,0,30%);
  box-shadow:0 5px 10px #0000004d;
  color:#fff;
  font-size:12px;
  font-weight:700;
  padding-block:15px;
  padding-inline:10px
}

.dndflow aside .nodes>*{box-shadow:5px 5px 10px 2px rgba(0,0,0,25%);
  box-shadow:5px 5px 10px 2px #00000040;cursor:grab;font-weight:500;
  margin-block-end:10px}.dndflow aside .description{margin-block-end:10px}

.dndflow .vue-flow-wrapper{
  flex-grow:1;
  block-size:100%
}

@media screen and (min-width: 640px){.dndflow{flex-direction:row}.dndflow aside{min-inline-size:25%}}

@media screen and (max-width: 639px){
  .dndflow aside .nodes{
    display:flex;
    flex-direction:row;
    gap:5px
  }
}

.vue-flow__node.intersecting{background-color:#eee}
</style>

<style scoped>
.dndflow {
  block-size: calc(100vh - 11rem);
  inline-size: 100%;
}
</style>
